<template>
  <div class="area-container">
    <div class="region-tree">
      <el-tree
        ref="regionTree"
        :data="dist"
        :node-key="nodeKey"
        :props="defaultProps"
        :expand-on-click-node="false"
        :default-expanded-keys="defaultExpands"
        :default-checked-keys="defaultCheckedKeys"
        accordion
        :indent="0"
        show-checkbox
        @check-change="handleCheckAllChange"
        @node-click="handleNodeClick"
      >
        <span
          slot-scope="{ node, data }"
          class="custom-tree-node"
        >
          <el-button
            type="text"
            :disabled="node.disabled"
            @click.stop="onCheckedNode(node, data)"
          >{{ node.label }}</el-button>
          <span v-if="node.level===2">
            <el-popover
              :ref="`reference[${data.id}]`"
              :value="visible===data.id"
              trigger="manual"
              :popper-options="{ boundariesElement: 'viewport', removeOnDestroy: true }"
              :offset="offset"
            >
              <div class="custom-areanode">
                <el-checkbox-group
                  v-model="data.checks"
                  @change="handleCheckedAreasChange($event, node, data.children)"
                >
                  <el-checkbox
                    v-for="area in data.children"
                    :key="area.id"
                    :label="area.id"
                    :disabled="data.disabled || area.disabled"
                    @click.stop.native="()=>{}"
                  >
                    {{ area.name }}
                  </el-checkbox>
                </el-checkbox-group>
              </div>
            </el-popover>
            <el-button
              type="text"
              icon="el-icon-caret-bottom"
              @click.stop="onTogglePopover(node, data)"
            />
          </span>
        </span>
      </el-tree>
    </div>
    <slot name="handle">
      <div
        v-if="actionVisible"
        class="area-actions"
      >
        <el-button @click="onSubmit">确定</el-button>
      </div>
    </slot>
  </div>
</template>

<script>
import { regionCitys } from '@/library'
export default {
  name: 'TransferTree',
  props: {
    value: {
      type: Array,
      default: () => {
        return []
      }
    },
    nodeKey: {
      type: String,
      default: 'id'
    },
    defaultProps: {
      type: Object,
      default: () => {
        return {
          children: 'children',
          label: 'name'
        }
      }
    },
    actionVisible: {
      type: Boolean,
      default: false
    }
  },
  data() {
    return {
      visible: false,
      areaNodes: regionCitys,
      areaNodesTree: [],
      dist: [],
      defaultCheckedKeys: [],
      disablesNodes: [],
      offset: 0
    }
  },
  computed: {
    defaultExpands() {
      return this.dist.map(item => {
        return item.id
      })
    },
    checkedCodes() {
      return this.value.map(code => {
        return code.substring(0, 4) + '00'
      })
    }
  },
  watch: {
    visible: {
      handler(v) {
        if (v) {
          var node = this.$refs.regionTree.getNode(v)
          var checkedChildren = node.childNodes.filter(item => {
            return item.checked
          })
          node.data.checks = checkedChildren.map(cnode => {
            return cnode.data.id
          })
        }
      },
      deep: true
    }
  },
  mounted() {
    this.dist = this.transferNodesToTree(regionCitys)
    console.log('format tree data', this.areaNodesTree)
    // this.$nextTick(() => {
    //   this.onMounteData(this.value)
    // })
  },
  methods: {
    onTogglePopover(node, data) {
      var elrefName = `reference[${data.id}]`
      this.$nextTick(() => {
        var dom = this.$refs[elrefName]
        console.log(dom)
        if (dom) {
          // this.offset = 1000
          this.visible = dom.showPopper ? false : data.id
          // dom.updatePopper()
        }
      })
    },
    handleCheckAllChange(val, checked, hasChecked) {
      console.log('all', checked)
      console.log('val', val)
      console.log('hasChecked', hasChecked)
      if (checked) {
        val.checks = val.children.map(item => {
          return item.id
        })
      } else if (!hasChecked) {
        val.checks = []
      }
    },
    handleCheckedAreasChange(value, node, data) {
      var $tree = this.$refs.regionTree
      if (value.length) {
        var itemKeys = data.map(item => {
          return item.id
        })
        var checkedKeys = $tree.getCheckedKeys(true)
        var checkeds = checkedKeys.filter(item => {
          return itemKeys.indexOf(item) === -1
        })
        var checks = checkeds.concat(value)
        $tree.setCheckedKeys(checks, true)
      } else {
        $tree.setChecked(node, false, true)
      }
    },
    onMounteData(data) {
      if (!(data && data.length)) {
        return
      }
      var codes = data.map(code => {
        return code.substring(0, 4) + '00'
      })
      var checkNodeIds = []
      for (var i = 0, size = this.areaNodes.length; i < size; i++) {
        var node = this.areaNodes[i]
        if (codes.indexOf(node.code) === -1) {
          continue
        }
        checkNodeIds.push(node.id)
      }
      this.defaultCheckedKeys = checkNodeIds
    },
    filterCheckedNodes(data) {
      return data.map(item => {
        const { children, ...params } = item
        console.log('reset node remove', children)
        return params
      })
    },
    onCheckedNode(node, data) {
      console.log('onCheckedNode', node)
      var $el = this.$refs.regionTree
      if (node.indeterminate) {
        // 半选状态弹出
        console.log('todo半选状态')
        if (this.visible !== data.id) {
          console.log('todo半选状态下，未显示当前元素下层节点')
          this.visible = data.id
        } else {
          console.log('todo半选状态下，显示元素下层节点中')
          $el.setChecked(node, true, true)
        }
      } else if (node.checked) {
        // 全选状态处理
        console.log('todo全选状态处理')
        $el.setChecked(node, false, true)
      } else {
        $el.setChecked(node, true, true)
        if (this.visible !== data.id) {
          this.visible = false
        }
      }
    },
    onSubmit() {
      var result = this.getChecks()
      this.$emit('input', result)
    },
    getChecks() {
      var $el = this.$refs.regionTree
      var nodes = $el.getCheckedNodes(false, true)
      console.log('nodes', nodes)
      return this.formatNodeResults(nodes)
    },
    formatNodeResults(data) {
      var pros = []
      var citys = {}
      for (var i = 0, size = data.length; i < size; i++) {
        var item = data[i]
        if (!item.parent_id) {
          continue
        }
        if (item.children && item.children.length) {
          // 省份
          pros.push({
            id: item.id,
            name: item.name,
            code: item.code,
            childs: item.children.length,
            parentName: '',
            parent_id: 0
          })
        } else {
          // 城市
          if (citys[item.parent_id]) {
            citys[item.parent_id].push({
              id: item.id,
              name: item.name,
              code: item.code,
              parent_id: item.parent_id
            })
          } else {
            citys[item.parent_id] = [
              {
                id: item.id,
                name: item.name,
                code: item.code,
                parent_id: item.parent_id
              }
            ]
          }
        }
      }
      var result = []
      for (i = 0, size = pros.length; i < size; i++) {
        var p = pros[i]
        var pchild = citys[p.id] || []
        var items = pchild.length
        if (items === p.childs) {
          delete citys[p.id]
          result.push(p)
        } else {
          for (var t = 0; t < pchild.length; t++) {
            result.push({ ...pchild[t], parentName: p.name })
          }
        }
      }
      return result
    },
    // 节点点击事件
    handleNodeClick(data, node) {
      if (this.visible !== data.id) {
        this.visible = data.id
      } else if (this.visible) {
        this.visible = false
      }
    },
    transferNodesToTree(data, rootId = 0, key = 'id', pk = 'parent_id') {
      const result = []
      if (!Array.isArray(data)) {
        return result
      }
      const map = {}
      var checkNodeIds = []
      var checkNodeCodes = this.checkedCodes
      var disableNodeCodes = this.disablesNodes
      for (var i = 0, size = data.length; i < size; i++) {
        var id = data[i][key]
        var node = { checks: [], disabled: false, children: [], ...data[i] }

        if (checkNodeCodes && checkNodeCodes.indexOf(node.code) !== -1) {
          console.log('checked node', node)
          checkNodeIds.push(node.id)
        }
        if (disableNodeCodes && disableNodeCodes.indexOf(node.code) !== -1) {
          console.log('disable node', node)
          node.disabled = true
        }
        map[id] = node
      }
      this.defaultCheckedKeys = checkNodeIds
      for (const i in map) {
        var item = map[i]
        var pid = item[pk]
        const parent = map[pid]
        if (parent) {
          (parent.children || (parent.children = [])).push(item)
        } else {
          if (rootId === pid) {
            result.push(item)
          }
        }
      }
      return result
    }
  }
}
</script>

<style lang="scss" scope>
.region-tree {
  .el-tree {
    .el-tree-node__expand-icon {
      order: 11;
      display: none;
    }
  }
  .el-tree > .el-tree-node {
    display: flex;
    & + .el-tree-node {
      margin-top: 10px;
    }
    & > .el-tree-node__content {
      width: 100px;
      & > .el-tree-node__expand-icon {
        display: none;
      }
    }
    & > .el-tree-node__children {
      flex-basis: 100%;
      display: grid;
      gap: 10px;
      grid-template-columns: repeat(auto-fill, calc(30% - 8px));
    }
  }
}
.custom-areanode {
  white-space: initial;
  .el-checkbox-group {
    // display: grid;
    // gap: 10px;
    // grid-template-columns: repeat(auto-fill, calc(200px - 8px));
  }
}
</style>
